#Boa:FramePanel:WXVISPANEL

import wx
import os, sys
import shutil
import time
import math
import vtk
import vtktudoss
import superthread
try:
    import extended.BaseCalc as BaseCalc
except ImportError:
    import BaseCalc
import pdb

def create(parent, root, renderwindow, primaryrenderer):
    return Annotation(parent,  root, renderwindow, primaryrenderer)


class Annotation:
    _pointsList = []
    _lineList = []
    _arcList = []
    _floatingLabelList = []
    initiateLabelTimer = True
    
    def __init__(self, parent, bla, renderwindow, primaryrenderer):
        self._root = bla
        self.baseCalc = BaseCalc.create(self, self)
        self.renderwindow = renderwindow
        self.renX = primaryrenderer
        self.InitializeAnnotationLayer()
        
    def InitializeAnnotationLayer(self):
        try:
            self.renderwindow.RemoveRenderer(self.renXannotation)
        except AttributeError:
            pass
        self.renderwindow.SetNumberOfLayers(2)
        self.renXannotation = vtk.vtkRenderer()
        self.renXannotation.SetLayer(1)
        self.renXannotation.InteractiveOff()
        self.renderwindow.AddRenderer(self.renXannotation)
        
    
        
    def VisualiseLine(self, point1, point2, opacity = 0.5, color = (1.0, 1.0, 1.0), actorcollection = None):
        polys = vtk.vtkCellArray()
        points = vtk.vtkPoints()
        points.InsertPoint(0, point1)
        points.InsertPoint(1, point2)
        polys.InsertNextCell(2)
        polys.InsertCellPoint(0)
        polys.InsertCellPoint(1)
        lijntje = vtk.vtkPolyData()
        lijntje.SetPoints(points)
        lijntje.SetLines(polys)
        ca = vtk.vtkActor()
        ma = vtk.vtkPolyDataMapper()
        ma.SetInput(lijntje)
        ca.SetMapper(ma)
        ca.GetProperty().SetColor(color)
        ca.GetProperty().SetOpacity(opacity)
        
        ca_transparent = vtk.vtkActor()
        ca_transparent.SetMapper(ma)
        ca_transparent.GetProperty().SetColor(1.0, 1.0, 1.0)
        ca_transparent.GetProperty().SetOpacity(0.33)
        
        self.renX.AddActor(ca)
        
        self.renXannotation.AddActor(ca_transparent)
        self.renXannotation.SetActiveCamera (self.renX.GetActiveCamera())
        
        
        
        self._lineList.append({'Actor' : ca})
        self._lineList.append({'Actor' : ca_transparent})
        
        if actorcollection != None:
            actorcollection.AddItem(ca)
            actorcollection.AddItem(ca_transparent)
            return actorcollection
        
        #pdb.set_trace()
    def VisualiseCoordinateSystem(self, OXYZ):
        O = OXYZ[0]
        X = OXYZ[1]
        Y = OXYZ[2]
        Z = OXYZ[3]
        self.VisualiseLine(O, self.baseCalc.AddPoints(O, self.baseCalc.MultiplyVector(X, 10)), color = (0.5, 0.0, 0.0), opacity = 1.0)
        #~ #self._root.annotation_renwin1.VisualisePoint(self.baseCalc.AddPoints(coordScapula_O, self.baseCalc.MultiplyVector(coordScapula_Z, 50)), "Zs" ,(1.00,1.00,0.15))
        self.VisualiseLine(O, self.baseCalc.AddPoints(O, self.baseCalc.MultiplyVector(Y, 10)), color = (0.0, 0.5, 0.0), opacity = 1.0)
        #~ #self._root.annotation_renwin1.VisualisePoint(self.baseCalc.AddPoints(coordScapula_O, self.baseCalc.MultiplyVector(coordScapula_X, 50)), "Xs" ,(1.00,1.00,0.15))
        self.VisualiseLine(O, self.baseCalc.AddPoints(O, self.baseCalc.MultiplyVector(Z, 10)), color = (0.0, 0.0, 0.5), opacity = 1.0)
        #~ #self._root.annotation_renwin1.VisualisePoint(self.baseCalc.AddPoints(coordScapula_O, self.baseCalc.MultiplyVector(coordScapula_Y, 50)), "Ys" ,(1.00,1.00,0.15))
        

    def VisualiseArc(self, point1, point2, point3, opacity = 0.5, color = (1.0, 1.0, 1.0)):    
        points = vtk.vtkPoints()
        points.InsertPoint(0, point1)
        points.InsertPoint(1, point2)
        points.InsertPoint(2, point3)
        
        polys = vtk.vtkCellArray()
        polys.InsertNextCell(3)
        polys.InsertCellPoint(0)
        polys.InsertCellPoint(1)
        polys.InsertCellPoint(2)

        lines = vtk.vtkCellArray()
        lines.InsertNextCell(2)
        lines.InsertCellPoint(0)
        lines.InsertCellPoint(1)
        lines.InsertNextCell(2)
        lines.InsertCellPoint(0)
        lines.InsertCellPoint(2)
            
        arcparts = 20
        vector1 = self.baseCalc.SubtractPoints(point2, point1)
        axis_length = self.baseCalc.Length3DVector(vector1)
        vtk.vtkMath().Normalize(vector1)
        vector2 = self.baseCalc.SubtractPoints(point3, point1)
        L2 = self.baseCalc.Length3DVector(vector2)
        if L2<axis_length:
            axis_length = L2
        vtk.vtkMath().Normalize(vector2)
        cross = [0,0,0]
        vtk.vtkMath().Cross(vector1, vector2, cross)
        dottie = math.acos(vtk.vtkMath.Dot(vector1,vector2) / (math.sqrt(math.pow(vector1[0],2)\
                             + math.pow(vector1[1],2) + math.pow(vector1[2],2))\
                             *math.sqrt(math.pow(vector2[0],2) + math.pow(vector2[1],2) \
                             + math.pow(vector2[2],2))))
        dottie = vtk.vtkMath.DegreesFromRadians(dottie)
        deel_dottie = dottie / (arcparts)
        transf = vtk.vtkTransform()
        triangleStripPoints = vtk.vtkPoints()
        triangleStripPoints.SetNumberOfPoints(arcparts*2+2)
        punt1 = self.baseCalc.AddPoints(point1, self.baseCalc.MultiplyVector(vector1, axis_length))
        punt2 = self.baseCalc.AddPoints(point1, self.baseCalc.MultiplyVector(vector1, 0.8*axis_length))
        triangleStripPoints.InsertPoint(0, punt1)
        triangleStripPoints.InsertPoint(1, punt2)
        for i in range(0,arcparts):
            transf.RotateWXYZ(deel_dottie, cross[0], cross[1], cross[2])
            transf.Update()
            a1_b = transf.TransformFloatPoint(vector1[0], vector1[1], vector1[2])
            punt1 = self.baseCalc.AddPoints(point1, self.baseCalc.MultiplyVector(a1_b, axis_length))
            punt2 = self.baseCalc.AddPoints(point1, self.baseCalc.MultiplyVector(a1_b, 0.8*axis_length))
            triangleStripPoints.InsertPoint(i*2+2, punt1)
            triangleStripPoints.InsertPoint(i*2+3, punt2)
        aTriangleStrip = vtk.vtkTriangleStrip()
        aTriangleStrip.GetPointIds().SetNumberOfIds((arcparts+1)*2)
        for i in range(0,arcparts+1):
            aTriangleStrip.GetPointIds().SetId(i*2, i*2)
            aTriangleStrip.GetPointIds().SetId(i*2+1, i*2+1)
        aTriangleStripGrid = vtk.vtkUnstructuredGrid()
        aTriangleStripGrid.Allocate(1, 1)
        aTriangleStripGrid.InsertNextCell(aTriangleStrip.GetCellType(), aTriangleStrip.GetPointIds())
        aTriangleStripGrid.SetPoints(triangleStripPoints)
        aTriangleStripMapper = vtk.vtkDataSetMapper()
        aTriangleStripMapper.SetInput(aTriangleStripGrid)
        

        vlakje = vtk.vtkPolyData()
        vlakje.SetPoints(points)
        vlakje.SetLines(lines)
        ma = vtk.vtkPolyDataMapper()
        ma.SetInput(vlakje)
        
        ca = vtk.vtkActor()
        ca.SetMapper(aTriangleStripMapper)
        ca.GetProperty().SetColor(color)
        ca.GetProperty().SetOpacity(opacity)
        ca_transparent = vtk.vtkActor()
        ca_transparent.SetMapper(aTriangleStripMapper)
        ca_transparent.GetProperty().SetColor(1.0, 1.0, 1.0)
        ca_transparent.GetProperty().SetOpacity(0.33)
        ca2 = vtk.vtkActor()
        ca2.SetMapper(ma)
        ca2.GetProperty().SetColor(color)
        ca2.GetProperty().SetOpacity(opacity)
        ca2_transparent = vtk.vtkActor()
        ca2_transparent.SetMapper(ma)
        ca2_transparent.GetProperty().SetColor(1.0, 1.0, 1.0)
        ca2_transparent.GetProperty().SetOpacity(0.33)
        
        
        self.renX.AddActor(ca)
        self.renX.AddActor(ca2)
        try:
            self.renderwindow.RemoveRenderer(self.renXannotation)
        except AttributeError:
            pass
        self.renderwindow.SetNumberOfLayers(2)
        self.renXannotation = vtk.vtkRenderer()
        self.renXannotation.SetLayer(1)
        self.renderwindow.AddRenderer(self.renXannotation)
        self.renXannotation.AddActor(ca_transparent)
        self.renXannotation.AddActor(ca2_transparent)
        self.renXannotation.SetActiveCamera (self.renX.GetActiveCamera())
        
        self._arcList.append({'Actor' : ca})
        self._arcList.append({'Actor' : ca_transparent})
        self._arcList.append({'Actor' : ca2})
        self._arcList.append({'Actor' : ca2_transparent})
        

            
    def VisualisePoint(self, point, pointName, color):
        ca = vtk.vtkCaptionActor2D()
        ca.GetProperty().SetColor(0.8,0.8,1)
        ca.GetCaptionTextProperty().SetColor(color)
        ca.GetCaptionTextProperty().ShadowOn()
        ca.SetPickable(0)
        ca.SetAttachmentPoint(point)
        ca.SetPosition(25,10)
        ca.BorderOff()
        ca.SetWidth(0.3)
        ca.SetHeight(0.04)
        ca.SetMaximumLeaderGlyphSize(10)        
        coneSource = vtk.vtkConeSource()
        coneSource.SetResolution(6)
        # we want the cone's very tip to be at 0,0,0
        coneSource.SetCenter(- coneSource.GetHeight() / 2.0, 0, 0)
        ca.SetLeaderGlyph(coneSource.GetOutput())    
        ca.GetProperty().SetColor(color)
        if len(pointName) > 0:
            ca.SetCaption(pointName)        
        else:
            ca.SetCaption("n/a")
        
        self.renX.AddActor(ca)
        self._pointsList.append({'point' : tuple(point),
                                 'name' : pointName,
                                 'sphereActor' : ca})

    def ClearArcList(self):
        for i in range(len(self._arcList)):
            # remove the  actor from the renderer
            self.renX.RemoveActor(self._arcList[0]['Actor'])
            self.renXannotation.RemoveActor(self._arcList[0]['Actor'])
            del self._arcList[0]
        #~ try:
            #~ self.renderwindow.RemoveRenderer(self.renXannotation)
        #~ except AttributeError:
            #~ pass
        #~ self.renderwindow.SetNumberOfLayers(1)

        
    def ClearLineList(self):
        for i in range(len(self._lineList)):
            # remove the  actor from the renderer
            self.renX.RemoveActor(self._lineList[0]['Actor'])
            self.renXannotation.RemoveActor(self._lineList[0]['Actor'])
            
            del self._lineList[0]
        #~ try:
            #~ self.renderwindow.RemoveRenderer(self.renXannotation)
        #~ except AttributeError:
            #~ pass
        #~ self.renderwindow.SetNumberOfLayers(1)

    def ClearPointList(self):
        for i in range(len(self._pointsList)):
            # remove the actor from the renderer
            self.renX.RemoveActor(self._pointsList[0]['sphereActor'])
            del self._pointsList[0]
            
    def ClearAll(self):
        self.ClearPointList()
        self.ClearLineList()
        self.ClearArcList()

    def AddFloatingLabel(self, _id = -1, _text = "", _position = [0,0],\
                                             _color = [1.0, 1.0, 1.0], _extinguish = 30): #time in 1/10 th sec.

        textActor = vtk.vtkTextActor()
        textActor.SetInput(_text)
        textActor.SetPosition(_position[0], _position[1])
        tprop = textActor.GetTextProperty()
        tprop.SetFontSize(32)
        tprop.SetFontFamilyToArial()
        tprop.SetJustificationToCentered()
        tprop.ShadowOn()
        tprop.SetColor(_color)
        tprop.SetOpacity(0)
        self.renX.AddActor(textActor)
        try:
            self._root.Render()
        except RuntimeError:
            pass
        
        self._floatingLabelList.append({'id': _id,
                                                     'actor': textActor,
                                                     'text' : _text,
                                                     'position' : _position,
                                                     'color' : _color,
                                                     'extinguish' : _extinguish,
                                                     'time': 0.0})        
        
        if self.initiateLabelTimer == True:
            self.FloatingLabelTimer()

    def FloatingLabelTimer(self):
        self.initiateLabelTimer = False        
        
        while len(self._floatingLabelList) > 0:
            i = len(self._floatingLabelList)-1
            terminationlist = []
            while i >= 0:
                label = self._floatingLabelList[i]
                if label['time'] < 15:
                    #Attack
                    a = label['time']
                    pos = label['position']
                    ratesqr = 2*(a/15.0)
                    label['actor'].SetPosition(pos[0], (pos[1] - ratesqr))
                    label['position'] = [pos[0], pos[1] - ratesqr]
                    tprop = label['actor'].GetTextProperty()
                    tprop.SetOpacity(a/15.0)
                    tprop.SetColor(label['color'])
                    
                elif label['time'] > label['extinguish']:
                    #Decay
                    a = (label['time'] - label['extinguish'])
                    pos = label['position']
                    label['actor'].SetPosition(pos[0], (pos[1] - 2))
                    label['position'] = [pos[0], (pos[1] - 2)]
                    tprop = label['actor'].GetTextProperty()
                    tprop.SetOpacity(1-a/15.0)
                    tprop.SetColor(label['color'])
                        
                    
                    if label['time'] == (label['extinguish'] + 15):                        
                        self.renX.RemoveActor(label['actor'])
                        label = self._floatingLabelList.pop(i)
                
                else:                    
                    pos = label['position']
                    label['actor'].SetPosition(pos[0], (pos[1] - 2))
                    label['position'] = [pos[0], (pos[1] - 2)]
                    
                i = i - 1 
                label['time'] = label['time'] + 1
                
            time.sleep(0.05)
            try:
                wx.Yield()
            except AssertionError:
                pass
            try:
                self._root.Render()
            except RuntimeError:
                pass

        self.initiateLabelTimer = True